<template>
  <div class="fill-width-height flex-col" style="padding: 12px;">
   <div class="flex-row gpa-10 flex-wrap" >
     <el-button type="primary" size="mini" @click="add" class="mr-0">新增<i class="el-icon-plus el-icon--right"></i></el-button>
     <el-button type="primary" size="mini" @click="edit" class="mr-0">编辑<i class="el-icon-edit el-icon--right"></i></el-button>
     <el-button type="success" size="mini" @click="materialLibManagement" class="mr-0">素材库<i class="el-icon-upload el-icon--right"></i></el-button>
     <el-button type="success" size="mini" @click="autoGenerateArticle" class="mr-0">生成文章</el-button>
     <el-button type="primary" size="mini" @click="writeTitle" class="mr-0">生成标题</el-button>
     <el-button type="warning" size="mini" @click="batchGenCoven" class="mr-0">生成封面</el-button>
     <el-button type="warning" size="mini" @click="batchDownCover" class="mr-0">下载封面</el-button>
     <el-button type="success" size="mini" @click="sendToDraftsBatch" class="mr-0" v-if="statusType === 'selected'" >发至草稿</el-button>
     <el-button type="primary" size="mini" @click="batchPublishedArticles" class="mr-0" v-if="statusType === 'selected'">发布</el-button>
     <el-button type="danger" size="mini" @click="confirmDeleteImageSelectData" class="mr-0">删除<i class="el-icon-delete el-icon--right"></i></el-button>
<!--     <el-input v-model="screenshotHeight" placeholder="截图的高度" style="width: 100px;"/>-->
   </div>
    <el-divider/>
    <ItemForm ref="itemFormRef" :mode="mode" :item="itemObj" @callBack="getPage"/>
    <MaterialLibManagement ref="materialLibManagementRef" />
    <AutoGenerateArticleItem ref="autoGenerateArticleItemRef" @callBack="getPage"/>
    <AiewArticle ref="viewArticleRef"/>

    <el-tabs type="border-card"  v-model="statusType" class="flex-1 overflow-hidden flex-col" @tab-click="handleClick">
      <el-tab-pane :name="item.id" :label="item.text" v-for="(item,index) in statusArr" :key="index" class="fill-height flex-col">
        <div class="overflow-auto" style="height: calc(100% - 40px)">
          <el-row :gutter="12" style="margin: 0;" v-if="statusType === item.id">
            <el-col :span="24" :md="6" :lg="6" v-for="dataItem in dataList" :key="dataItem.id" style="padding: 6px;">
              <el-card class="thumbnail-card flex-col height-410">
                <template #header>
                  <div class="flex-row" @click.stop="handleThumbnailSelect(dataItem)">
                    <el-checkbox
                      v-model="dataItem.selected"
                    ></el-checkbox>
                    <div class="flex-1"></div>
                    <div class="flex-row" style="gap: 10px">
                      <el-button type="text" text @click="viewArticle(dataItem)">查看</el-button>
<!--                      <el-button type="text" text @click="downCover(dataItem.id, dataItem.title,true)">下封面</el-button>-->
                      <el-button type="text" text @click="lookCover(dataItem)" v-if="dataItem.coverurl && dataItem.coverurl.length > 0">看封面</el-button>
                      <el-button type="text" text @click="selectedArticles(dataItem)" v-if="dataItem.articestatus === 'toBeSel'">选择</el-button>
<!--                      <el-button type="text" text @click="sendToDrafts(dataItem)" v-if="dataItem.articestatus === 'selected'">至草稿</el-button>-->
                      <el-button type="text" text @click="publishedArticles(dataItem.id)" v-if="dataItem.articestatus === 'selected'">发布</el-button>
                      <el-button type="text" text @click="confirmDeleteImage(dataItem.id)" style="color: red;">删除</el-button>
                    </div>
                  </div>
                </template>
                <div class="fill-width-height flex-col flex-1 " style="min-height: 0;" @click.stop="handleThumbnailSelect(dataItem, true)">
                  <div class="flex-row" style="padding: 10px 0;">
                    <span class="text-bold">{{ dataItem.title }} </span>
                    <div class="flex-1"></div>
                    <span v-if="dataItem.publicaccountName" class="el-button--text" style="width: 113px;">【{{ dataItem.publicaccountName }}】</span>
                  </div>
                  <div class="flex-1 overflow-auto">
                    <div v-html="dataItem.contents" :id="dataItem.id" ></div>
                  </div>
                </div>
              </el-card>
            </el-col>
          </el-row>
        </div>

        <div style="padding: 10px;">
          <el-divider/>
          <div class="flex-row">
            <div class="flex-row">
              <span>全选/反选：</span>
              <el-checkbox v-model="selectedAll" @change="selectedAllChange"></el-checkbox>
            </div>
            <pagination
              :total="total"
              :page-sizes="[100, 200, 300, 500]"
              :page.sync="queryParams.pageNum"
              :limit.sync="queryParams.pageSize"
              @pagination="getPage"
              style="margin: 0!important; padding: 0!important; position: unset;"
            />
          </div>
        </div>
      </el-tab-pane>
    </el-tabs>

    <!-- 公众号选择模态框 -->
    <el-dialog :visible.sync="sendToDraftDialogVisible" title="选择公众号" width="30%" :before-close="handleDialogClose">
      <el-form ref="publicAccountFormRef" :model="publicAccountForm" :rules="publicAccountRules" label-width="100px">
        <el-form-item label="选择公众号" prop="publicAccountId">
          <el-select v-model="publicAccountForm.publicAccountId" placeholder="请选择公众号" style="width: 100%;">
            <el-option v-for="item in publicAccountList" :key="item.id" :label="item.name" :value="item.id"/>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleDialogClose">取消</el-button>
          <el-button type="primary" @click="confirmSendToDraft">确认</el-button>
        </span>
      </template>
    </el-dialog>

    <el-dialog :visible.sync="lookCoverVisible" title="查看封面" width="30%">
      <el-image :src="lookCoverSrc"/>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="downImg(lookCoverSrc,'cover')">下载</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>

import {
  createDraft,
  deleteById,
  page,
  published,
  selected,
  updateCoverUrl,
  upload, writeTitleByArticleId
} from '@/api/imgManage/writeArticles'
import requirePool from '@/utils/requirePool'
import './snapdom'
import {getPublicAccountList} from "@/api/imgManage/publicAccount";
export default {
  name: '',
  components: {
    ItemForm: () => import('./itemForm'),
    MaterialLibManagement: () => import('./materialLibManagement'),
    AutoGenerateArticleItem: () => import('./autoGenerateArticleItem'),
    AiewArticle: () => import('./viewArticle.vue'),
  },
  props: {},
  data() {
    return {
      selectedAll: false,
      statusType: 'toBeSel',
      statusArr: [
        { id: 'toBeSel', text: '待选' },
        { id: 'selected', text: '已选' },
        { id: 'published', text: '已发布' }
      ],
      coverImgUrl: '',

      dataList: [],
      total: 0,
      queryParams: {
        pageNum: 1,
        pageSize: 100
      },

      publicAccountList: [],
      sendToDraftDialogVisible: false,
      publicAccountForm: {
        publicAccountId: ''
      },
      publicAccountRules: {
        publicAccountId: [{ required: true, message: '请选择公众号', trigger: 'change' }]
      },
      itemObj: {},
      mode: 'add',
      screenshotHeight: 200,

      lookCoverSrc: '',
      lookCoverVisible: false
    }
  },
  computed: {},
  methods: {
    published,
    add(){
      this.mode = 'add'
      this.$refs.itemFormRef.showDialog()
    },
    edit(){
      this.mode = 'edit'
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      if(selectList?.length !== 1){
        return this.$message.warning("只能选择一条数据");
      }
      this.$set(this,'itemObj',Object.assign({}, selectList[0]))
      this.$nextTick(() => {
        this.$refs.itemFormRef.showDialog()
      })
    },
    viewArticle(item){
      this.$refs.viewArticleRef.init(item)
    },
    handleClick(tab, event){
      this.queryParams.pageNum = 1
      this.getPage()
    },
    autoGenerateArticle(){
      this.$refs.autoGenerateArticleItemRef.init()
    },
    materialLibManagement(){
      this.$refs.materialLibManagementRef.init()
    },
    async publishedArticles(id){
      this.$modal.confirm('是否确认发布这个文吗？').then(function() {
        return published({ id: id } );
      }).then(() => {
        this.getPage();
        this.$modal.msgSuccess("发布成功");
      }).catch(() => {});
    },
    async selectedArticles(item){
      // 打开自定义模态框
      this.openSendToDraftDialog(item);
    },
    // 打开发送到草稿箱模态框
    openSendToDraftDialog(item) {
      this.currentSendArticleItem = item;
      this.publicAccountForm.publicAccountId = this.publicAccountList.length > 0 ? this.publicAccountList[0].id : '';
      this.sendToDraftDialogVisible = true;
    },
    async confirmSendToDraft() {
      this.$refs.publicAccountFormRef.validate(async (valid) => {
        if (valid) {
          try {
            await selected({ id: this.currentSendArticleItem.id,
              publicAccountId: this.publicAccountForm.publicAccountId } )
            await this.getPage();
            this.$message.success("选择成功");
            this.sendToDraftDialogVisible = false;
          } catch (error) {
            console.error('选择失败', error);
            this.$message.error("选择失败：" + (error.response?.data?.message || error.message));
          } finally {

          }
        }
      });
    },

    // 关闭模态框
    handleDialogClose(done) {
      this.sendToDraftDialogVisible = false;
      if (done) done();
    },
    async writeTitle(){
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      if(selectList?.length !== 1){
        return this.$message.warning("只能选择一条数据");
      }
      const item = selectList[0]
      const newTitle = await writeTitleByArticleId({ id: item.id}).then(res => res.data)
      item.title = newTitle
    },
    batchGenCoven(){
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      this.$modal.loading("正在截图，请稍候...");

      const taskList = selectList.map(item =>
        this.downCover(item.id, item.title, false)
      )
      requirePool(taskList,5).then(res => {
        this.successCallBack()
        this.$modal.closeLoading()
      }).catch(e => {
        this.$modal.closeLoading()
      })
    },
    batchDownCover(){
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      selectList.forEach(item =>
        this.downCover(item.id, item.title, true)
      )
    },
    batchPublishedArticles(){
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      this.$modal.confirm('是否确认发布这' + selectList.length +'篇文吗？').then(function() {
        const ids = selectList.map(item => item.id)?.join(',')
        return published({ id: ids } );
      }).then(() => {
        this.getPage();
        this.$modal.msgSuccess("发布成功");
      }).catch(() => {});
    },
    async sendToDraftsBatch(){
      if (!this.publicAccountList || this.publicAccountList.length === 0) {
        return this.$message.error("没有可用的公众号，请先配置公众号");
      }
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      this.$modal.confirm('确认将这'+ selectList.length +'篇文章发送到公众号草稿箱？').then(async () => {
        try {
          for (const item of selectList) {
            if(item?.coverUrl?.length === 0){
              console.log('截图',item.id)
              await this.downCover(item.id, item.title, false)
            }
          }
          console.log('截图完成')

          this.$modal.loading("正在发送到草稿箱，请稍候...");

          const ids = selectList.map(item => item.id)?.join(',')

          await createDraft({ ids: ids });
          this.sendToDraftDialogVisible = false;
          await this.getPage();
          this.$message.success("发送成功");
        } catch (error) {
          console.error('发送到草稿箱失败', error);
          this.$message?.error("发送失败：" + (error.response?.data?.message || error.message));
        } finally {
          // 隐藏加载状态
          this.$modal?.closeLoading();
        }
      })
    },
    async sendToDrafts(item){
      // 检查是否有公众号
      if (!this.publicAccountList || this.publicAccountList.length === 0) {
        return this.$message.error("没有可用的公众号，请先配置公众号");
      }
      this.$modal.confirm('确认是否发送到公众号草稿箱？').then(async () => {
        try {
          if(!item?.coverUrl){
            await this.downCover(item.id,item.title,false)
          }
          this.$modal.closeLoading();
          this.$modal.loading("正在发送到草稿箱，请稍候...");

          await createDraft({
            ids: item.id,
          });

          this.sendToDraftDialogVisible = false;
          await this.getPage();
          this.$message.success("发送成功");
        } catch (error) {
          console.error('发送到草稿箱失败', error);
          this.$message?.error("发送失败：" + (error.response?.data?.message || error.message));
        } finally {
          // 隐藏加载状态
          this.$modal?.closeLoading();
        }
      }).catch(() => {});
    },
    async getPublicAccountList(){
      const res = await getPublicAccountList()
      this.publicAccountList =  res.data
    },
    selectedAllChange(){
      this.$nextTick(() => {
        setTimeout(() => {
          this.dataList.forEach(item => this.$set(item,'selected', this.selectedAll))
        },50)
      })
    },
    async getPage(){
      this.dataList = []
      this.selectedAll = false
      const res = await page({ ...this.queryParams , articestatus: this.statusType})

      res.rows?.forEach(item => {
        const accObj = this.publicAccountList?.find(accItem => item.publicaccountid === accItem.id)
        if(accObj){
          item.publicaccountName = accObj.name
        }
      })

      this.dataList = res.rows
      this.total = res.total
      // setTimeout(() => {
      //   this.batchCaptureWithCache()
      // },1000)
    },
    handleThumbnailSelect(item,isFlag){
      if(isFlag){
        this.dataList.forEach(dt => {
          if(dt.id !== item.id){
            this.$set(dt,'selected', false)
          }
        })
      }
      this.$set(item,'selected', !item.selected)
    },
     replaceImagesWithProxy(refs){
      const baseUrl = this.$config.urlFormat('/proxy')
      let images = refs.querySelectorAll('img');
      const domain = window.location.origin;
      console.log('domain', domain)
      images.forEach( img => {
        if (img.src && img.src.startsWith('http') && !img.src.startsWith(domain) && !img.dataset.proxyConverted) {
          img.src = `${baseUrl}&url=${encodeURIComponent(img.src)}`
          // 设置成已转换
          img.dataset.proxyConverted = 'true';
        }
      });
    },
    /**
     * 将 snapdom 捕获的内容调整为指定比例，并用白色填充空白区域
     * @param {Object} capture - snapdom 捕获的对象
     * @param {number} [targetRatio=2.35] - 目标宽高比 (宽/高)
     * @returns {HTMLCanvasElement} - 调整后的 canvas 元素
     */
    resizeToAspectRatio(capture, targetRatio = 2.35) {
      return new Promise(async (resolve, reject) => {
        let canvas = await capture.toCanvas()
        // 创建新画布
        const newCanvas = document.createElement('canvas');
        const ctx = newCanvas.getContext('2d');

        // 获取原始图像数据
        const originalImage = new Image();
        originalImage.src = canvas.toDataURL("image/png");

        originalImage.onload = () => {
          const originalRatio = canvas.width / canvas.height;
          if (originalRatio < targetRatio) {
            newCanvas.width = canvas.height * targetRatio;
            newCanvas.height = canvas.height;
            ctx.fillStyle = 'white';
            ctx.fillRect(0, 0, newCanvas.width, newCanvas.height);
            const offsetX = (newCanvas.width - canvas.width) / 2;
            ctx.drawImage(
              originalImage,
              offsetX, 0,
              canvas.width, canvas.height
            );
          } else {
            newCanvas.width = canvas.width;
            newCanvas.height = canvas.width / targetRatio;
            const offsetY = (newCanvas.height - canvas.height) / 2;
            ctx.fillStyle = 'white';
            ctx.fillRect(0, 0, newCanvas.width, newCanvas.height);
            ctx.drawImage(
              originalImage,
              0, offsetY,
              canvas.width, canvas.height
            );
          }
          resolve(newCanvas)
        };
      })
    },
    batchCaptureWithCache(){
      this.dataList.forEach(item => {
        if(!item.coverUrl || item.coverUrl?.length === 0){
          const element = document.getElementById(item.id)
          this.captureWithCache(element).then(() => {
            console.log(item.id + ' 缓存完成')
          })
        }
      })
    },
    // 按需预缓存
    async captureWithCache(element) {
      if(!element){
        return
      }
      // 首次截图前预缓存
      if (!element?.dataset?.cached) {
        await window.preCache(element);
        if(!element.dataset){
          element.dataset = {}
        }
        element.dataset.cached = 'true';
      }
    },
    async downCover(id, title,isDown = true){
      let coverUrl = this.dataList.find(item => item.id === id)?.coverUrl
      if(coverUrl && coverUrl?.startsWith('/api/images') && isDown){
        coverUrl = this.$config.urlFormat(coverUrl,false)
        return this.downImg(coverUrl, title);
      }

      this.$modal.loading("正在截图中，请稍候...");
      const element = document.getElementById(id);
      this.replaceImagesWithProxy(element)
      // 等待图片加载
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const capture = await window.snapdom(element, {
        scale: 2,
        backgroundColor: '#fff',
        embedFonts: true,
        compress: true
      });
      // 调整比例
      const resizedCanvas = await this.resizeToAspectRatio(capture, 2.35);
      this.coverImgUrl = resizedCanvas.toDataURL("image/png");
      if(isDown){
        this.downImg(this.coverImgUrl, title);
      }
      await this.uploadCoverImage(id,this.coverImgUrl,title)
      this.$modal.closeLoading()
    },
    async uploadCoverImage(id,coverImgUrl,title){
      // 上传封面图像
      const response = await this.uploadImage(coverImgUrl, title).catch(error => {
        console.error('上传失败:', error);
        this.$message.error('封面上传失败');
        this.$modal.closeLoading();
      });
      await updateCoverUrl({ id: id, coverUrl: response.url}).catch(error => {
        this.$modal.closeLoading();
      });
      console.log('上传成功:', response);
      this.$message.success('封面上传成功');
    },
    downImg(imgUrl, fileName) {
      this.$modal.loading("正在下载，请稍候...");
      const link = document.createElement('a');
      link.href = imgUrl;
      const timestamp = new Date().getTime();
      link.download = fileName ? `${fileName}.png` : `封面图_${timestamp}.png`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      this.$modal.loading("下载完成");
    },
    lookCover(item){
      if(item.coverurl?.length === 0){
        return this.$message.warning('封面地址为空！');
      }
      let coverUrl = item.coverurl
      if(coverUrl?.startsWith('/api/images')){
        coverUrl = this.$config.urlFormat(coverUrl,false)
      }
      this.lookCoverSrc = coverUrl
      this.lookCoverVisible = true
    },
    // 将DataURL转换为Blob对象
    dataURLToBlob(dataURL) {
      const arr = dataURL.split(',');
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);

      while(n--){
        u8arr[n] = bstr.charCodeAt(n);
      }

      return new Blob([u8arr], {type: mime});
    },

    // 上传图像到服务器
    async uploadImage(dataURL, title) {
      try {
        // 将DataURL转换为Blob
        const blob = this.dataURLToBlob(dataURL);

        // 创建FormData对象
        const formData = new FormData();
        formData.append('file', blob, `${title}.png`);
        // 发送请求到后端
        const response = await upload(formData);
        console.log('uploadResponse ', response)
        return response;
      } catch (error) {
        console.error('上传过程中出错:', error);
        throw error;
      }
    },

    confirmDeleteImageSelectData(){
      const selectList = this.dataList?.filter(item => item.selected)
      if(selectList?.length === 0){
        return this.$message.warning("请先选择数据");
      }
      this.$modal.confirm('确认删除这'+ selectList.length +'篇文章吗？').then(async () => {
          try {
            const ids = selectList.map(item => item.id).join(',')
            return deleteById({ ids: ids } );
          } catch (error) {
              console.error('删除失败:', error);
              this.$message.error('删除失败');
            }
          }).then(() => {
            this.getPage();
            this.$modal.msgSuccess("删除成功");
          }).catch(() => {});
    },
    confirmDeleteImage(id){
      this.$modal.confirm('是否确认删除数据？').then(function() {
        return deleteById({ ids: id } );
      }).then(() => {
        this.getPage();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {});
    }
  },
  async mounted() {
    await this.getPublicAccountList()
    await this.getPage()
  }
}
</script>


<style scoped lang="scss">
::v-deep{
  .el-card__header{
    min-height: unset;
  }
  .el-card__body{
    overflow: hidden;
  }
}
.mr-0 {
  margin: 0
}
.gpa-10 {
  gap: 10px;
}
</style>
